<?php

namespace api\modules\backend\controllers;

use api\modules\backend\models\Bus;
use api\modules\backend\models\Driver;
use api\modules\backend\models\Gift;
use api\modules\backend\models\Guide;
use api\modules\backend\models\Hotel;
use api\modules\backend\models\Journey;
use api\modules\backend\models\JourneyGift;
use api\modules\backend\models\JourneyGuide;
use api\modules\backend\models\JourneyHotel;
use api\modules\backend\models\JourneyMeal;
use api\modules\backend\models\JourneyTraffic;
use api\modules\backend\models\Restaurant;
use api\modules\backend\models\RestaurantMeal;
use yii\data\Pagination;
use common\commands\Common;
use Yii;
use yii\filters\auth\QueryParamAuth;

/**
 * Journey Controller API
 *
 * @author Fong <xiaofeng.zhang@suppernovachina.com>
 */
class JourneyController extends ControllerBase
{
    public $modelClass = 'api\modules\backend\models\Journey';
    private $notDeleted = 0; //未删除状态
    private $deleted = 1; //已删除状态
    private $active = 1; //可用状态 可用
    private $journey_id; //行程id

    public function behaviors()
    {
        $behaviors = parent::behaviors();
        $behaviors['authenticator'] = [
            'class' => QueryParamAuth::className(),
            'optional' => [],
        ];
        $behaviors['authenticator']['except'] = ['options'];

        return $behaviors;
    }

    /**
     * 行程列表
     */
    public function actionIndex()
    {
        $get = Yii::$app->request->get();

        $line_id = is_numeric($get['line_id']) ? $get['line_id'] : 0;

        $where = [
            'line_id' => $line_id,
            'is_deleted' => $this->notDeleted
        ];
        $get['serial'] = isset($get['serial']) ? $get['serial'] : '';
        if (isset($get['active']) && is_numeric($get['active'])) $where['active'] = $get['active'];

        $journeyModelClass = new Journey();
        $journeyFields = array(
            'journey_id',
            'departure_date',
            'day',
            'serial',
            'max',
            'create_time',
            'update_time',
            'active',
        );
        $journeyQuery = $journeyModelClass::find()->select($journeyFields)->where($where)
            ->andwhere([
                'and',
                ['like', 'serial', $get['serial']],
            ]);

        $countQuery = clone $journeyQuery;
        $pages = new Pagination(['totalCount' => $countQuery->count()]);
        $journey = $journeyQuery->offset($pages->offset)
            ->limit($pages->limit)
            ->orderBy(['update_time' => SORT_DESC, 'create_time' => SORT_DESC])
            ->asArray()
            ->all();

        $meta = array('totalCount' => (int)$pages->totalCount, 'perPage' => $pages->getPageSize(), 'pageCount' => $pages->getPageCount(), 'currentPage' => $pages->getPage() + 1);
        $result = array('item' => $journey, '_meta' => $meta);

        $this->success($result);
    }

    /**
     * 线路关联数据
     */
    public function actionData()
    {
        $guideModelClass = new Guide();
        $guides = $guideModelClass::find()->where(['active' => $this->active, 'is_deleted' => $this->notDeleted])->asArray()->all();

        $driverModelClass = new Driver();
        $drivers = $driverModelClass::find()->where(['active' => $this->active, 'is_deleted' => $this->notDeleted])->asArray()->all();

        $busModelClass = new Bus();
        $buses = $busModelClass::find()->where(['active' => $this->active, 'is_deleted' => $this->notDeleted])->asArray()->all();

        $hotelModelClass = new Hotel();
        $hotels = $hotelModelClass::find()->where(['active' => $this->active, 'is_deleted' => $this->notDeleted])->asArray()->all();

        $restaurantModelClass = new Restaurant();
        $restaurants = $restaurantModelClass::find()->where(['active' => $this->active, 'is_deleted' => $this->notDeleted])->asArray()->all();

        $restaurantMealModelClass = new RestaurantMeal();
        $restaurantMealWhere = [
            'r.is_deleted' => $this->notDeleted,
            'r.active' => $this->active,
            'rm.is_deleted' => $this->notDeleted,
            'rm.active' => $this->active
        ];
        $restaurantMeals = $restaurantMealModelClass::find()->from('{{%restaurant_meal}} as rm')->select(['`rm`.*'])
            ->leftJoin('{{%restaurant}} as r', 'r.restaurant_id = rm.restaurant_id')
            ->where($restaurantMealWhere)
            ->asArray()
            ->all();

        foreach ($restaurants as $key => $restaurant) {
            $restaurant_id = $restaurant['restaurant_id'];
            $restaurants[$key]['children'] = array_values(array_filter($restaurantMeals, function ($t) use ($restaurant_id) {
                return $t['restaurant_id'] == $restaurant_id;
            }));
        }

        $giftModelClass = new Gift();
        $gifts = $giftModelClass::find()->where(['active' => $this->active, 'is_deleted' => $this->notDeleted])->asArray()->all();

        $data = [
            'guides' => $guides,
            'hotels' => $hotels,
            'drivers' => $drivers,
            'buses' => $buses,
            'restaurants' => $restaurants,
            'gifts' => $gifts
        ];

        $this->success($data);
    }

    /**
     * 新增行程
     * @throws \yii\db\Exception
     */
    public function actionCreate()
    {
        $time = time();
        $post = Yii::$app->request->post();

        $journeyModelClass = new Journey();
        $journeyModelClass->line_id = $post['line_id'];
        $journeyModelClass->serial = $post['serial'];
        $journeyModelClass->departure_date = $post['departure_date'];
        $journeyModelClass->day = $post['day'];
        $journeyModelClass->is_hotel = $post['is_hotel'];
        $journeyModelClass->is_meal = $post['is_meal'];
        $journeyModelClass->is_gift = $post['is_gift'];
        $journeyModelClass->max = $post['max'];
        $journeyModelClass->departure_address = $post['departure_address'];
        $journeyModelClass->back_address = $post['back_address'];
        $journeyModelClass->apply_amount = $post['apply_amount'];
        $journeyModelClass->remark = $post['remark'];
        $journeyModelClass->active = $post['active'];
        $journeyModelClass->create_time = $time;
        $journeyModelClass->update_time = $time;

        $tr = Yii::$app->db->beginTransaction();
        try {

            if (!$journeyModelClass->save()) {
                throw new \Exception('DATABASE_FAILED');
            }

            $this->journey_id = $journeyModelClass->journey_id;

            if (!self::insertGuide()) {
                throw new \Exception('DATABASE_FAILED');
            }

            if (!self::insertTraffic()) {
                throw new \Exception('DATABASE_FAILED');
            }

            if ($post['is_hotel']) {
                if (!self::insertHotel()) {
                    throw new \Exception('DATABASE_FAILED');
                }
            }

            if ($post['is_meal']) {
                if (!self::insertMeal()) {
                    throw new \Exception('DATABASE_FAILED');
                }
            }

            if ($post['is_gift']) {
                if (!self::insertGift()) {
                    throw new \Exception('DATABASE_FAILED');
                }
            }

            $tr->commit();

        } catch (\Exception $e) {
            $tr->rollBack();
            $this->response(Common::getPackedResponse(DATABASE_FAILED, Yii::t('app', $e->getMessage())));
        }

        $this->success(array('id' => (string)$journeyModelClass->journey_id));
    }

    /**
     * 行程详情
     */
    public function actionView()
    {
        $get = Yii::$app->request->get();

        $journey_id = is_numeric($get['id']) ? $get['id'] : 0;

        $journeyModelClass = new Journey();
        $journeyFields = [
            'journey_id',
            'serial',
            'departure_date',
            'day',
            'apply_amount',
            'is_hotel',
            'is_meal',
            'is_gift',
            'max',
            'departure_address',
            'back_address',
            'remark',
            'active'
        ];
        $journey = $journeyModelClass::find()->select($journeyFields)
            ->where(['journey_id' => $journey_id, 'is_deleted' => $this->notDeleted])
            ->asArray()
            ->one();

        $journey['hotels'] = [];
        $journey['meals'] = [];
        $journey['gifts'] = [];
        if ($journey) {
            if ($journey['is_hotel']) {
                $journeyHotelModelClass = new JourneyHotel();
                $journeyHotelFields = [
                    'hotel_id',
                    'live_day',
                    'cost'
                ];
                $hotels = $journeyHotelModelClass::find()->select($journeyHotelFields)
                    ->where(['journey_id' => $journey_id])
                    ->asArray()
                    ->all();

                foreach ($hotels as $hotel) {
                    $journey['hotels'][$hotel['live_day']][] = [
                        'value' => $hotel['hotel_id'],
                        'cost' => $hotel['cost']
                    ];
                }

                $this->reset_array_key($journey['hotels']);
            }

            if ($journey['is_meal']) {
                $journeyMealModelClass = new JourneyMeal();
                $journeyMealFields = [
                    '`jm`.`restaurant_id`',
                    '`jm`.`restaurant_meal_id`',
                    'mealtime',
                    'day',
                    'cost',
                    'number',
                    'table_number',
                    'each_cost'
                ];
                $meals = $journeyMealModelClass::find()->from('{{%journey_meal}} as `jm`')->select($journeyMealFields)
                    ->leftJoin('{{%restaurant_meal}} as `rm`', '`rm`.`restaurant_meal_id` = `jm`.`restaurant_meal_id`')
                    ->where(['journey_id' => $journey_id])
                    ->asArray()
                    ->all();

                foreach ($meals as $meal) {
                    if (!isset($journey['meals'][$meal['day']][$meal['restaurant_meal_id']])) {
                        $journey['meals'][$meal['day']][$meal['restaurant_meal_id']] = $meal;
                        $journey['meals'][$meal['day']][$meal['restaurant_meal_id']]['value'] = [$meal['restaurant_id'], $meal['restaurant_meal_id']];
                        $journey['meals'][$meal['day']][$meal['restaurant_meal_id']]['mealtime'] = [];
                    }

                    $journey['meals'][$meal['day']][$meal['restaurant_meal_id']]['mealtime'][] = $meal['mealtime'];
                }

                $this->reset_array_key($journey['meals']);
            }

            if ($journey['is_gift']) {
                $journeyGiftModelClass = new JourneyGift();
                $journeyGiftFields = [
                    'value' => 'gift_id',
                    'cost',
                    'quantity'
                ];
                $journey['gifts'] = $journeyGiftModelClass::find()->select($journeyGiftFields)
                    ->where(['journey_id' => $journey_id])
                    ->asArray()
                    ->all();
            }

            $journeyGuideModelClass = new JourneyGuide();
            $journeyGuideFields = [
                'value' => 'guide_id',
                'cost'
            ];
            $journey['guides'] = $journeyGuideModelClass::find()->select($journeyGuideFields)
                ->where(['journey_id' => $journey_id])
                ->asArray()
                ->all();

            $journeyTraffic = new JourneyTraffic();
            $journeyTrafficFields = [
                'driver_id',
                'driver_cost',
                'bus_id',
                'bus_cost',
            ];
            $journey['drivers'] = $journeyTraffic::find()->select($journeyTrafficFields)
                ->where(['journey_id' => $journey_id])
                ->asArray()
                ->all();
        }

        $data = array('journey' => $journey);
        $this->success($data);
    }

    /**
     * 更新行程
     * @throws \yii\db\Exception
     */
    public function actionUpdate()
    {
        $get = Yii::$app->request->get();
        $post = Yii::$app->request->post();

        $this->journey_id = $journey_id = is_numeric($get['id']) ? $get['id'] : 0;

        if (empty($journey_id)) {
            $errorString = Yii::t('app', '{attribute} does not exist!', ['attribute' => Yii::t('app', 'journey_id')]);
            $this->response(Common::getPackedResponse(DATABASE_FAILED, $errorString));
        }

        $journeyModelClass = new Journey();
        $journey = $journeyModelClass::findOne(['journey_id' => $journey_id, 'is_deleted' => $this->notDeleted]);

        if (empty($journey)) {
            $errorString = Yii::t('app', '{attribute} does not exist!', ['attribute' => Yii::t('app', 'journey')]);
            $this->response(Common::getPackedResponse(DATABASE_FAILED, $errorString));
        }

        $journey->departure_date = $post['departure_date'];
        $journey->day = $post['day'];
        $journey->apply_amount = $post['apply_amount'];
        $journey->is_hotel = $post['is_hotel'] ? 1 : 0;
        $journey->is_meal = $post['is_meal'] ? 1 : 0;
        $journey->is_gift = $post['is_gift'] ? 1 : 0;
        $journey->serial = $post['serial'];
        $journey->max = $post['max'];
        $journey->departure_address = $post['departure_address'];
        $journey->back_address = $post['back_address'];
        $journey->remark = $post['remark'];
        $journey->active = $post['active'];
        $journey->update_time = time();

        if (!$journey->validate()) {//验证数据
            $this->response(Common::getPackedResponse(DATABASE_FAILED, 'DATABASE_FAILED'));
        }

        $tr = Yii::$app->db->beginTransaction();//事务 如果失败 就会滚数据
        try {
            if (!$journey->update()) {
                throw new \Exception('DATABASE_FAILED1');
            }

            JourneyGuide::deleteAll(['journey_id' => $journey_id]);
            JourneyHotel::deleteAll(['journey_id' => $journey_id]);
            JourneyTraffic::deleteAll(['journey_id' => $journey_id]);
            JourneyMeal::deleteAll(['journey_id' => $journey_id]);
            JourneyGift::deleteAll(['journey_id' => $journey_id]);

            if (!self::insertGuide()) {
                throw new \Exception('DATABASE_FAILED1');
            }

            if (!self::insertTraffic()) {
                throw new \Exception('DATABASE_FAILED2');
            }

            if ($post['is_hotel']) {
                if (!self::insertHotel()) {
                    throw new \Exception('DATABASE_FAILED3');
                }
            }

            if ($post['is_meal']) {
                if (!self::insertMeal()) {
                    throw new \Exception('DATABASE_FAILED4');
                }
            }

            if ($post['is_gift']) {
                if (!self::insertGift()) {
                    throw new \Exception('DATABASE_FAILED4');
                }
            }

            $tr->commit();
        } catch (\Exception $e) {
            $tr->rollBack();
            $this->response(Common::getPackedResponse(DATABASE_FAILED, $e->getMessage()));
        }

        $this->success(array('journey_id' => $journey_id));
    }

    /**
     * 删除行程
     * @throws \yii\db\Exception
     */
    public function actionDelete()
    {
        $get = Yii::$app->request->get();

        $journey_id = is_numeric($get['id']) ? $get['id'] : 0;

        $journeyModelClass = new Journey();
        $journey = $journeyModelClass::findOne(['journey_id' => $journey_id, 'is_deleted' => $this->notDeleted]);

        if (empty($journey)) {
            $this->response(Common::getPackedResponse(DATABASE_FAILED, 'DATABASE_FAILED'));
        }

        $journey->is_deleted = $this->deleted;

        $tr = Yii::$app->db->beginTransaction();//事务 如果失败 就会滚数据
        try {

            if (!$journey->update()) {
                throw new \Exception('DATABASE_FAILED');
            }

            $tr->commit();
        } catch (\Exception $e) {
            $tr->rollBack();
            $this->response(Common::getPackedResponse(DATABASE_FAILED, 'DATABASE_FAILED'));
        }

        $this->success(array('journey_id' => $journey_id));
    }

    /**
     * 重置多维数组键值
     * @param $ar
     */
    function reset_array_key(&$ar)
    {
        if (!is_array($ar)) return;
        $ar = array_values($ar);

        foreach ($ar as $k => &$v) {
            if (is_array($v)) $v = array_values($v);
        }
    }

    /**
     * 插入行程导游
     * @return bool
     * @throws \yii\db\Exception
     */
    public function insertGuide()
    {
        $post = Yii::$app->request->post();

        $journeyGuideKey = ['journey_id', 'guide_id', 'cost'];
        $journeyGuideValue = [];

        foreach ($post['guides'] as $guide) {
            if (!$guide['value']) continue;
            $journeyGuideValue[] = [$this->journey_id, $guide['value'], $guide['cost']];
        }

        $res = \Yii::$app->db->createCommand()->batchInsert(JourneyGuide::tableName(), $journeyGuideKey, $journeyGuideValue)->execute();

        return is_numeric($res);
    }

    /**
     * 插入行程交通
     * @return bool
     * @throws \yii\db\Exception
     */
    public function insertTraffic()
    {
        $post = Yii::$app->request->post();

        $journeyTrafficKey = ['journey_id', 'driver_id', 'driver_cost', 'bus_id', 'bus_cost'];
        $journeyTrafficValue = [];

        foreach ($post['drivers'] as $driver) {
            if (!$driver['driver_id'] || !$driver['bus_id']) continue;
            $journeyTrafficValue[] = [$this->journey_id, $driver['driver_id'], $driver['driver_cost'], $driver['bus_id'], $driver['bus_cost']];
        }

        $res = \Yii::$app->db->createCommand()->batchInsert(JourneyTraffic::tableName(), $journeyTrafficKey, $journeyTrafficValue)->execute();

        return is_numeric($res);
    }

    /**
     * 插入行程酒店
     * @return bool
     * @throws \yii\db\Exception
     */
    public function insertHotel()
    {
        $post = Yii::$app->request->post();

        $journeyHotelKey = ['journey_id', 'hotel_id', 'live_day', 'cost'];
        $journeyHotelValue = [];

        foreach ($post['hotels'] as $key => $hotel) {
            foreach ($hotel as $h) {
                if (!$h['value']) continue;
                $journeyHotelValue[] = [$this->journey_id, $h['value'], $h['day'], $h['cost']];
            }
        }

        $res = \Yii::$app->db->createCommand()->batchInsert(JourneyHotel::tableName(), $journeyHotelKey, $journeyHotelValue)->execute();

        return is_numeric($res);
    }

    /**
     * 插入行程餐标
     * @return bool
     * @throws \yii\db\Exception
     */
    public function insertMeal()
    {
        $post = Yii::$app->request->post();

        $journeyMealKey = ['journey_id', 'restaurant_id', 'restaurant_meal_id', 'day', 'mealtime', 'cost', 'number', 'table_number'];
        $journeyMealValue = [];

        foreach ($post['meals'] as $key => $meal) {
            foreach ($meal as $m) {
                foreach ($m['mealtime'] as $mealtime) {
                    $journeyMealValue[] = [$this->journey_id, $m['value'][0], $m['value'][1], $m['day'], $mealtime, $m['cost'], $m['number'], $m['table_number']];
                }
            }
        }

        $res = \Yii::$app->db->createCommand()->batchInsert(JourneyMeal::tableName(), $journeyMealKey, $journeyMealValue)->execute();

        return is_numeric($res);
    }

    /**
     * 插入行程礼品
     * @return bool
     * @throws \yii\db\Exception
     */
    public function insertGift()
    {
        $post = Yii::$app->request->post();

        $journeyGiftKey = ['journey_id', 'gift_id', 'cost', 'quantity'];
        $journeyGiftValue = [];

        foreach ($post['gifts'] as $key => $gift) {
            if (!$gift['value']) continue;
            $journeyGiftValue[] = [$this->journey_id, $gift['value'], $gift['cost'], $gift['quantity']];
        }

        $res = \Yii::$app->db->createCommand()->batchInsert(JourneyGift::tableName(), $journeyGiftKey, $journeyGiftValue)->execute();

        return is_numeric($res);
    }
}